<template>
  <div class="register-container">
    <el-card class="register-card">
      <template #header>
        <div class="card-header">
          <span>注册新用户</span>
        </div>
      </template>
      <el-form ref="formRef" :model="form" label-width="100px" @submit.prevent="handleRegister">
        <!-- 用户名 -->
        <el-form-item
          :rules="[{ required: true, message: '请输入用户名', trigger: 'blur' }]"
          label="用户名"
          label-for="username"
        >
          <div style="display: flex; align-items: center">
            <el-input
              id="username"
              v-model="form.username"
              placeholder="请输入用户名"
              style="flex: 1"
              @input="onUsernameInput"
            />
            <el-button
              v-if="showCheckUsernameButton"
              :loading="checkingUsername"
              size="small"
              style="margin-left: 8px"
              type="primary"
              @click="checkUsername"
            >
              检测用户名
            </el-button>
          </div>
        </el-form-item>

        <!-- 昵称 -->
        <el-form-item
          v-if="showNickname"
          :rules="[{ required: true, message: '请输入昵称', trigger: 'blur' }]"
          label="昵称"
          label-for="nickname"
        >
          <el-input
            id="nickname"
            v-model="form.nickname"
            placeholder="请输入昵称(不输入默认为用户名)"
          />
        </el-form-item>
        <el-form-item v-else label="昵称">
          <el-button type="text" @click="showNickname = true">自定义昵称</el-button>
        </el-form-item>

        <!-- 邮箱 -->
        <el-form-item
          :rules="[
            { required: true, message: '请输入邮箱', trigger: 'blur' },
            { validator: validateEmail, trigger: ['blur', 'change'] },
          ]"
          label="邮箱"
          label-for="email"
          prop="email"
        >
          <el-input id="email" v-model="form.email" placeholder="请输入邮箱" />
        </el-form-item>

        <!-- 密码 -->
        <el-form-item
          :rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]"
          label="密码"
          label-for="password"
        >
          <el-input
            id="password"
            v-model="form.password"
            placeholder="请输入密码"
            show-password
            type="password"
          />
        </el-form-item>

        <!-- 确认密码 -->
        <el-form-item
          :rules="[
            { required: true, message: '请确认密码', trigger: 'blur' },
            { validator: validateConfirmPassword, trigger: ['blur', 'change'] },
          ]"
          label="确认密码"
          label-for="confirmPassword"
          prop="confirmPassowrd"
        >
          <el-input
            id="confirmPassword"
            v-model="form.confirmPassowrd"
            placeholder="请再次输入密码"
            show-password
            type="password"
          />
        </el-form-item>

        <!-- 用户角色 -->
        <el-form-item
          :rules="[{ required: true, message: '请选择用户角色', trigger: 'change' }]"
          label="用户角色"
          label-for="role"
        >
          <el-radio-group id="role" v-model="form.role">
            <el-radio label="STUDENT">学生</el-radio>
            <el-radio label="TEACHER">教师</el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- 验证码 -->
        <el-form-item
          v-show="codeSentTemp"
          :rules="[{ required: true, message: '请输入验证码', trigger: 'blur' }]"
          label="验证码"
          label-for="code"
        >
          <el-input id="code" v-model="form.code" placeholder="请输入验证码" />
        </el-form-item>

        <!-- 获取验证码按钮 -->
        <el-form-item>
          <el-button
            :disabled="codeSent || !validEmail || sendCodeLoading"
            type="primary"
            @click="handleSendCode"
          >
            {{ codeSent ? `重新发送 (${countdown}s)` : '获取验证码' }}
          </el-button>
        </el-form-item>

        <!-- 注册与返回登录按钮 -->
        <el-form-item>
          <el-button
            :disabled="isFormInvalid"
            :loading="loading"
            native-type="submit"
            type="primary"
          >
            注册
          </el-button>
          <el-button @click="goToLogin">返回登录</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/authStore'
import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus'

const router = useRouter()
const authStore = useAuthStore()
const formRef = ref<FormInstance | null>(null)

const checkingUsername = ref(false)
const showCheckUsernameButton = ref(true)

const form = reactive({
  username: '',
  nickname: '',
  email: '',
  password: '',
  confirmPassowrd: '',
  role: 'STUDENT',
  code: '',
})

const showNickname = ref(false)
const codeSent = ref(false)
const codeSentTemp = ref(false)
const loading = ref(false)
const sendCodeLoading = ref(false)
const countdown = ref(0)
let timer: number | null = null

// 邮箱格式正则校验
const validEmail = computed(() => {
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return re.test(form.email)
})

// 用户名输入时，按钮恢复显示
function onUsernameInput() {
  showCheckUsernameButton.value = true
}

// 校验用户名是否已存在
async function checkUsername() {
  if (!form.username) {
    ElMessage.warning('请输入用户名后再检测')
    return
  }
  checkingUsername.value = true
  try {
    const exists = await authStore.checkUsernameExists(form.username)
    if (exists) {
      ElMessage.error('用户名已被占用，请更换其他用户名')
      showCheckUsernameButton.value = true
    } else {
      ElMessage.success('用户名可用')
      showCheckUsernameButton.value = false
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
  } catch (error) {
    ElMessage.error('检测失败，请稍后再试')
    showCheckUsernameButton.value = true
  } finally {
    checkingUsername.value = false
  }
}

// 邮箱格式校验函数
function validateEmail(rule: unknown, value: string, callback: (error?: Error) => void) {
  if (!value) {
    callback(new Error('请输入邮箱'))
  } else if (!validEmail.value) {
    callback(new Error('邮箱格式不正确'))
  } else {
    callback()
  }
}

watch(
  () => form.email,
  () => {
    formRef.value?.validateField('email')
  },
)

// 实时校验确认密码是否一致
watch([() => form.password, () => form.confirmPassowrd], () => {
  formRef.value?.validateField('confirmPassowrd')
})

function validateConfirmPassword(rule: unknown, value: string, callback: (error?: Error) => void) {
  if (value !== form.password) {
    callback(new Error('两次输入密码不一致'))
  } else {
    callback()
  }
}

// 发送验证码
const handleSendCode = async () => {
  if (!validEmail.value) {
    ElMessage.error('请输入有效的邮箱地址')
    return
  }
  sendCodeLoading.value = true
  try {
    await authStore.sendEmailVerificationEmail(form.email)
    ElMessage.success('验证码已发送，请查收邮箱')
    codeSentTemp.value = true
    codeSent.value = true
    countdown.value = 30

    timer = window.setInterval(() => {
      countdown.value--
      if (countdown.value <= 0) {
        codeSent.value = false
        sendCodeLoading.value = false
        if (timer) {
          clearInterval(timer)
          timer = null
        }
      }
    }, 1000)
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
  } catch (e) {
    ElMessage.error('验证码发送失败，请确认邮箱是否已被注册')
    sendCodeLoading.value = false
  }
}

const isFormInvalid = computed(() => {
  return (
    !form.username ||
    !validEmail.value ||
    !form.password ||
    !form.confirmPassowrd ||
    form.password !== form.confirmPassowrd ||
    !form.role ||
    !form.code
  )
})

// 提交注册
const handleRegister = () => {
  loading.value = true
  formRef.value?.validate(async (valid) => {
    if (!valid) {
      loading.value = false
      return
    }

    try {
      await authStore.register(form)
      ElMessage.success('注册成功，已自动登录！')
      await router.push('/dashboard')
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
    } catch (error) {
      ElMessage.error('注册失败，用户名或验证码可能有误！')
    } finally {
      loading.value = false
    }
  })
}

const goToLogin = () => {
  router.push('/login')
}
</script>

<style scoped>
.register-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f0f2f5;
}

.register-card {
  width: 450px;
}

.card-header {
  text-align: center;
  font-size: 20px;
}
</style>
